﻿using Core.AdminUI.V2.Middleware;
using Core.AdminUI.V2.Utils;
using Core.FrameWork.Commons.ApiResult;
using Core.FrameWork.Commons.Loging;
using Core.FrameWork.Models;
using Core.FrameWork.Models.Enum.User;
using Core.FrameWork.Models.Models.System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace Core.AdminUI.V2.Filter
{
    /// <summary>
    /// 记录行为日志
    /// </summary>
    public class RecordAccessActionFilterAsync : IAsyncActionFilter
    {
        private readonly Stopwatch _stopwatch;
        /// <summary>
        /// 构造函数
        /// </summary>
        public RecordAccessActionFilterAsync()
        {
            _stopwatch = new Stopwatch();
        }
        /// <summary>
        /// 执行器
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {

            await next();

            var user = context.HttpContext.GetCurrentUser();

            if (!string.IsNullOrEmpty(user.Id))//是否已授权

            {
                var api = context.HttpContext.Request.Path;//路径

                //获取行为名称
                //获取attribute
                var notActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
                var notAttributes = notActionDescriptor.MethodInfo.GetCustomAttributes(typeof(NotLogAttribute), false);
                if (notAttributes != null && notAttributes.Count() > 0)
                {
                    //context.HttpContext.Response.OnCompleted();
                }
                else
                {



                    if (context.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest")// 过滤记录的接口行为
                    {
                        _stopwatch.Restart();
                        var sysNLogAdminRecords = new SysNLogAdminRecords();

                        HttpRequest request = context.HttpContext.Request;

                        sysNLogAdminRecords.Url = api;
                        sysNLogAdminRecords.UserId = Guid.Parse(user.Id);
                        sysNLogAdminRecords.UserName = user.Name;
                        sysNLogAdminRecords.IpAddress = IPLogHandlerMiddleware.GetClientIp(context.HttpContext);
                        sysNLogAdminRecords.CreateTime = DateTime.Now;
                        sysNLogAdminRecords.RequestMethod = request.Method;
                        sysNLogAdminRecords.Agent = request.Headers["User-Agent"].ToString();

                        // 获取请求body内容
                        if (request.Method.ToLower().Equals("post") || request.Method.ToLower().Equals("put"))
                        {
                            // 启用倒带功能，就可以让 Request.Body 可以再次读取
                            request.EnableBuffering();

                            Stream stream = request.Body;
                            byte[] buffer = new byte[request.ContentLength.Value];
                            await stream.ReadAsync(buffer, 0, buffer.Length);
                            sysNLogAdminRecords.RequestParamsString = Encoding.UTF8.GetString(buffer);

                            request.Body.Position = 0;
                        }
                        else if (request.Method.ToLower().Equals("get") || request.Method.ToLower().Equals("delete"))
                        {
                            sysNLogAdminRecords.RequestParamsString = HttpUtility.UrlDecode(request.QueryString.ToString(), Encoding.UTF8);
                        }
                        //获取行为名称
                        //获取attribute
                        var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
                        var attributes = actionDescriptor.MethodInfo.GetCustomAttributes(typeof(ActionDescriptionAttribute), false);

                        if (attributes != null && attributes.Count() > 0)
                        {
                            var actionInfo = attributes[0] as ActionDescriptionAttribute;
                            sysNLogAdminRecords.ActionName = actionInfo.ActionName;
                            if (actionInfo.LogResponseData)//开启记录响应 Body内容
                            {
                                //// 获取Response.Body内容
                                //var originalBodyStream = context.HttpContext.Response.Body;
                                //using (var responseBody = new MemoryStream())
                                //{
                                //    context.HttpContext.Response.Body = responseBody;

                                //    var responseBodyData = await GetResponse(context.HttpContext.Response);

                                //    await responseBody.CopyToAsync(originalBodyStream);

                                //    sysNLogAdminRecords.ResponseData = responseBodyData;
                                //}
                            }
                        }

                        var dt = DateTime.Now;

                        // 响应完成记录时间和存入日志
                        context.HttpContext.Response.OnCompleted(async () =>
                        {
                            _stopwatch.Stop();

                            sysNLogAdminRecords.ResponseTime = _stopwatch.ElapsedMilliseconds;

                            using var conetxt = context.HttpContext.RequestServices.GetService<AdminContext>();

                            await conetxt.AddAsync(sysNLogAdminRecords);

                            await conetxt.SaveChangesAsync();

                            // 自定义log输出
                            var requestInfo = System.Text.Json.JsonSerializer.Serialize(sysNLogAdminRecords);
                            Parallel.For(0, 1, e =>
                            {
                                LogLockHelper.OutSql2Log("RecordAccessLogs", "RecordAccessLogs" + dt.ToString("yyyy-MM-dd"), new string[] { requestInfo + "," }, false);
                            });
                        });

                    }
                }
            }

        }
        /// <summary>
        /// 获取响应内容
        /// </summary>
        /// <param name="response"></param>
        /// <returns></returns>
        public async Task<string> GetResponse(HttpResponse response)
        {
            response.Body.Seek(0, SeekOrigin.Begin);
            var text = await new StreamReader(response.Body).ReadToEndAsync();
            response.Body.Seek(0, SeekOrigin.Begin);
            return text;
        }

    }
}
